/*
 * Copyright (c) 2010 Curtis Boyden.  All rights reserved. 
 * This software was developed by Curtis Boyden and is provided under the terms 
 * of the GNU Lesser General Public License, Version 2.1. You may not use 
 * this file except in compliance with the license. If you need a copy of the license, 
 * please go to http://www.gnu.org/licenses/lgpl-2.1.txt. The Original Code is ejMud
 * (Ewerp Java MUD).  The Initial Developer is Curtis Boyden.
 *
 * Software distributed under the GNU Lesser Public License is distributed on an "AS IS" 
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or  implied. Please refer to 
 * the license for the specific language governing your rights and limitations.
 */

package com.ewerp.server.sessions;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.ewerp.server.plugins.AbstractPlugin;
import com.ewerp.server.plugins.ILifecycleListener;
import com.ewerp.server.sessions.ISession;
import com.ewerp.server.sessions.ISessionFactory;
import com.ewerp.server.sessions.ISessionManager;

/**
 * This session manager uses {@link ISessionFactory}s to create and register its
 * {@link ISession}s.
 * 
 * To add a new {@link ISessionFactory} add it to the sessionFactoryList
 * property in the Init() method. {@link ISessionFactory}s that are registered
 * to this session manager may optionally implement the
 * {@link ILifecycleListener} interface and have the lifecycle methods invoked
 * in sync with this session manager's lifecycle methods.
 * 
 * @author cboyden
 * 
 */
public class EwerpSessionManager extends AbstractPlugin implements ISessionManager, ILifecycleListener {
    protected static EwerpSessionManager instance = new EwerpSessionManager();

    protected List<ISessionFactory> sessionFactoryList = new ArrayList<ISessionFactory>();

    protected List<ISession> sessionList = new ArrayList<ISession>();

    public static EwerpSessionManager getInstance() {
        if (instance == null) {
            instance = new EwerpSessionManager();
        }

        return instance;
    }

    protected EwerpSessionManager() {
    }

    @Override
    public List<Class<?>> getInterfaces() {
        return Arrays.asList(new Class<?>[] { ISessionManager.class });
    }

    @Override
    public void init() {
        // If not externally set, load the default factories and register this
        // session manager
        if (sessionFactoryList.size() <= 0) {
            // Default ISessionFactory list is built here
        }

        for (ISessionFactory sessionFactory : sessionFactoryList) {
            sessionFactory.registerSessionManager(this);
            if (sessionFactory instanceof ILifecycleListener) {
                ((ILifecycleListener) sessionFactory).init();
            }
        }
    }

    @Override
    public void start() {
        for (ISessionFactory sessionFactory : sessionFactoryList) {
            if (sessionFactory instanceof ILifecycleListener) {
                ((ILifecycleListener) sessionFactory).start();
            }
        }
    }

    @Override
    public void stop() {
        // Send the shutdown signal to all active sessions
        for (ISession session : sessionList) {
            session.shutdown();
        }

        // Stop all session factories
        for (ISessionFactory sessionFactory : sessionFactoryList) {
            if (sessionFactory instanceof ILifecycleListener) {
                ((ILifecycleListener) sessionFactory).stop();
            }
        }
    }

    @Override
    public void addSession(ISession session) throws IllegalArgumentException {
        if (session == null) {
            throw new IllegalArgumentException("parameter 'session' must not be null");
        }
        session.setPluginManager(getPluginManager());
        sessionList.add(session);
    }

    @Override
    public void removeSession(ISession session) throws IllegalArgumentException {
        if (session == null) {
            throw new IllegalArgumentException("parameter 'session' must not be null");
        }
        sessionList.remove(session);
    }

    /**
     * DO NOT USE! Package level method FOR UNIT TESTING ONLY.
     * 
     * @return
     */
    List<ISession> getSessionList() {
        return sessionList;
    }

    /**
     * DO NOT USE! Package level method FOR UNIT TESTING ONLY.
     * 
     * @return
     */
    void addSessionFactory(ISessionFactory sessionFactory) {
        sessionFactoryList.add(sessionFactory);
    }
}
